package org.joa.manager.simulated;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.InvocationTargetException;

import org.joa.actor.Actor;
import org.joa.actor.ActorName;
import org.joa.actor.exception.RemoteException;
import org.joa.actor.transaction.Transaction;
import org.joa.manager.ActorManager;
import org.joa.manager.ActorManagerInterface;

public class SimulatedRemoteActorManager implements ActorManagerInterface {
    private ActorManager actorManager;

    public SimulatedRemoteActorManager(ActorManager actorManager) {
        this.actorManager = actorManager;
    }

    @Override
    public Serializable invoke(ActorName actorName, String methodName, Serializable[] params,
        Transaction transaction) throws IOException, ClassNotFoundException,
        IllegalArgumentException, IllegalAccessException, InvocationTargetException,
        RemoteException {

        // Serialize parameters
        ByteArrayOutputStream byteOutput = new ByteArrayOutputStream();
        ObjectOutputStream output = new ObjectOutputStream(byteOutput);
        output.writeObject(params);

        // Deserialize params
        ObjectInputStream input =
            new ObjectInputStream(new ByteArrayInputStream(byteOutput.toByteArray()));

        params = (Serializable[]) input.readObject();

        return actorManager.invoke(actorName, methodName, params, transaction);
    }

    @Override
    public Serializable createActorProxy(ActorName owner, Class<? extends Actor> actorClass,
        Class<?> interfaceClass) {
        return actorManager.createActorProxy(owner, actorClass, interfaceClass);
    }

    @Override
    public Serializable createActorProxy(ActorName remote, ActorName owner, Class<?> interfaceClass) {
        return actorManager.createActorProxy(remote, owner, interfaceClass);
    }
}
